# 线段树，超时
# class TreeNode:
#     def __init__(self):
#         self.lu = self.ld = self.ru = self.rd = None
#         self.sum = 0
#         self.lazy = False
#
#
# class Solution(object):
#     def rectangleArea(self, rectangles):
#         tree = TreeNode()
#         maxRange = 1000000
#
#         def down(node):
#             if not node.lu:
#                 node.lu = TreeNode()
#                 node.ld = TreeNode()
#                 node.ru = TreeNode()
#                 node.rd = TreeNode()
#
#         def judge(x1, y1, x2, y2, m1, n1, m2, n2):
#             if x1 > x2 or y1 > y2:
#                 return False
#             else:
#                 l1 = max(x1, m1)
#                 t1 = max(y1, n1)
#                 l2 = min(x2, m2)
#                 t2 = min(y2, n2)
#                 return (max(0, l2 - l1 + 1)) * (max(0, t2 - t1 + 1)) > 0
#
#         def update(node, x1, y1, x2, y2, m1, n1, m2, n2):
#             if node.lazy:
#                 return
#             if x1 >= m1 and y1 >= n1 and x2 <= m2 and y2 <= n2:
#                 node.sum = (x2 - x1 + 1) * (y2 - y1 + 1)
#                 node.lazy = True
#                 return
#             x_mid = (x1 + x2) // 2
#             y_mid = (y1 + y2) // 2
#             down(node)
#             if judge(x1, y1, x_mid, y_mid, m1, n1, m2, n2):
#                 update(node.ld, x1, y1, x_mid, y_mid, m1, n1, m2, n2)
#             if judge(x1, y_mid + 1, x_mid, y2, m1, n1, m2, n2):
#                 update(node.lu, x1, y_mid + 1, x_mid, y2, m1, n1, m2, n2)
#             if judge(x_mid + 1, y1, x2, y_mid, m1, n1, m2, n2):
#                 update(node.rd, x_mid + 1, y1, x2, y_mid, m1, n1, m2, n2)
#             if judge(x_mid + 1, y_mid + 1, x2, y2, m1, n1, m2, n2):
#                 update(node.ru, x_mid + 1, y_mid + 1, x2, y2, m1, n1, m2, n2)
#             up(node)
#
#         def up(node):
#             node.sum = (node.lu.sum + node.ld.sum + node.ru.sum + node.rd.sum) % (10 ** 9 + 7)
#
#         for rec in rectangles:
#             update(tree, 0, 0, maxRange, maxRange, rec[0], rec[1], rec[2] - 1, rec[3] - 1)
#         return tree.sum
# 扫描线
import sortedcontainers
class Solution(object):
    def rectangleArea(self, rectangles):
        events = []
        for x1, y1, x2, y2 in rectangles:
            events.append([y1, 1, x1, x2])
            events.append([y2, 0, x1, x2])
        events.sort()

        def query():
            ans = 0
            cur = -1
            for [x1, x2] in active:
                cur = max(x1, cur)
                ans += max(0, x2 - cur)
                cur = max(x2, cur)
            return ans

        l_cur = events[0][0]
        active = sortedcontainers.SortedList()
        ans = 0
        for y, state, x1, x2 in events:
            ans += (y - l_cur) * query()
            if state:
                active.add([x1, x2])
            else:
                active.remove([x1, x2])
            l_cur = y

        return ans % (10 ** 9 + 7)


data = Solution()
rectangles = [[0, 0, 2, 2]]
print(data.rectangleArea(rectangles))
# rectangles = [[0, 0, 1000000000, 1000000000]]
# print(data.rectangleArea(rectangles))
# rectangles = [[0, 0, 1, 1], [2, 2, 3, 3]]
# print(data.rectangleArea(rectangles))
